Reporting on LinkModuleDescriptors

Can anyone figure out what's wrong with this code? It causes DOORS to crash.
 

void reportOnLMDs(Folder fGiven) {
    
        if ( (null fGiven) || (isDeleted fGiven) )
                return
 
        LinkModuleDescriptor LMD
        
        for LMD in fGiven do {
                string strSourceName = (getSourceName LMD) ""
                if (strSourceName == "")
                        continue
                print (getSourceName LMD) "\t"
                print (getTargetName LMD) "\t"
                print (getName LMD) "\t"
                print (getDescription LMD) "\t"
                print (getMandatory LMD) "\t"
                print (getOverridable LMD) "\t"
                ModName_ mn = module(strSourceName)
                if ((!isDeleted mn) && (exists mn))
                        print (getLinkModuleDescriptorsExclusive(fGiven, mn)) "\n"
        }
        
}

 


Hint: commenting out the getLinkModuleDescriptorsExclusive(fGiven, mn) line makes everything run without crashing.

Does anyone have any idea why this code causes the crash?

 


kbmurphy - Thu Sep 06 13:50:14 EDT 2012

Re: Reporting on LinkModuleDescriptors
Gedinfo - Thu Sep 06 16:02:29 EDT 2012

Break up
 

print (getLinkModuleDescriptorsExclusive(fGiven, mn)) "\n"


to

{code}
bool bStatus = getLinkModuleDescriptorsExclusive(fGiven, mn)
print bStatus "\n"

Re: Reporting on LinkModuleDescriptors
Gedinfo - Thu Sep 06 16:03:31 EDT 2012

Break up
 

print (getLinkModuleDescriptorsExclusive(fGiven, mn)) "\n"


to

 

 

bool bStatus = getLinkModuleDescriptorsExclusive(fGiven, mn)
print bStatus "\n"

 

 

Re: Reporting on LinkModuleDescriptors
kbmurphy - Thu Sep 06 16:16:38 EDT 2012

Gedinfo - Thu Sep 06 16:03:31 EDT 2012

Break up
 

print (getLinkModuleDescriptorsExclusive(fGiven, mn)) "\n"


to

 

 

bool bStatus = getLinkModuleDescriptorsExclusive(fGiven, mn)
print bStatus "\n"

 

 

Thanks ged!

Unfortunately that was one of the first things that I tried. What happens is that DOORS appears to hang when I run this. Without those lines of code, it runs flawlessly and pretty fast too.

Re: Reporting on LinkModuleDescriptors
kbmurphy - Thu Sep 06 16:17:08 EDT 2012

kbmurphy - Thu Sep 06 16:16:38 EDT 2012
Thanks ged!

Unfortunately that was one of the first things that I tried. What happens is that DOORS appears to hang when I run this. Without those lines of code, it runs flawlessly and pretty fast too.

I accidentally marked this question as answered. I don't believe I can undo this...

Re: Reporting on LinkModuleDescriptors
llandale - Thu Sep 06 17:28:59 EDT 2012

I notice it aborts in the loop statement, not the function statement.

My intuitive wild guess is that the offending function has within it a "for LMD in this Folder" loop; which will conflict with your outer "for LMD in fGiven" loop. It may not be intutively obvious, but in DXL that is the same as having an "for i" loop inside another "for i" loop.

What did I say? That function messes up your LMD loop.

SOP is then to do this:

void reportOnLMDs(Folder fGiven) {
    
        if ( (null fGiven) || (isDeleted fGiven) )
                return
 
        Skip skp = create()
        int  Sequencer = 0
        LinkModuleDescriptor LMD
        
        for LMD in fGiven do
        {  put(skp, Sequencer++, LMD)
        }
 
        for LMD in skp do {
                string strSourceName = (getSourceName LMD) ""
                if (strSourceName == "")
                        continue
                print (getSourceName LMD) "\t"
                print (getTargetName LMD) "\t"
                print (getName LMD) "\t"
                print (getDescription LMD) "\t"
                print (getMandatory LMD) "\t"
                print (getOverridable LMD) "\t"
                ModName_ mn = module(strSourceName)
                if ((!isDeleted mn) && (exists mn)) //
                {  bool b = getLinkModuleDescriptorsExclusive(fGiven, mn)
                   print b
                }
                print "\n"
        }
        delete(skp)
        
}
 
reportOnLMDs(current Folder)


Notice now the offending function's internal "for LMD in Folder" loop is inside a "for LMD in Skip" loop, and does not mess that up.

-Louie

There is something else wrong here but I got to go....

Re: Reporting on LinkModuleDescriptors
kbmurphy - Fri Sep 07 18:11:49 EDT 2012

llandale - Thu Sep 06 17:28:59 EDT 2012

I notice it aborts in the loop statement, not the function statement.

My intuitive wild guess is that the offending function has within it a "for LMD in this Folder" loop; which will conflict with your outer "for LMD in fGiven" loop. It may not be intutively obvious, but in DXL that is the same as having an "for i" loop inside another "for i" loop.

What did I say? That function messes up your LMD loop.

SOP is then to do this:

void reportOnLMDs(Folder fGiven) {
    
        if ( (null fGiven) || (isDeleted fGiven) )
                return
 
        Skip skp = create()
        int  Sequencer = 0
        LinkModuleDescriptor LMD
        
        for LMD in fGiven do
        {  put(skp, Sequencer++, LMD)
        }
 
        for LMD in skp do {
                string strSourceName = (getSourceName LMD) ""
                if (strSourceName == "")
                        continue
                print (getSourceName LMD) "\t"
                print (getTargetName LMD) "\t"
                print (getName LMD) "\t"
                print (getDescription LMD) "\t"
                print (getMandatory LMD) "\t"
                print (getOverridable LMD) "\t"
                ModName_ mn = module(strSourceName)
                if ((!isDeleted mn) && (exists mn)) //
                {  bool b = getLinkModuleDescriptorsExclusive(fGiven, mn)
                   print b
                }
                print "\n"
        }
        delete(skp)
        
}
 
reportOnLMDs(current Folder)


Notice now the offending function's internal "for LMD in Folder" loop is inside a "for LMD in Skip" loop, and does not mess that up.

-Louie

There is something else wrong here but I got to go....

Hey Louie,

Your explanation makes sense and doesn't at the same time. I'm not deleting anything, nor am I changing anything, and it's those two functions that you have to be careful of in a for loop. I'm merely reporting on things.

Still, I tried your sample code, and unfortunately it crashed.

I have a helper function that is calling this function for each folder recursively. I doubt that the helper function is what's causing this issue as I'm only passing folders and projects as fGiven.

Still stumped....

Re: Reporting on LinkModuleDescriptors
Peter_Albert - Mon Sep 10 04:25:10 EDT 2012

kbmurphy - Fri Sep 07 18:11:49 EDT 2012
Hey Louie,

Your explanation makes sense and doesn't at the same time. I'm not deleting anything, nor am I changing anything, and it's those two functions that you have to be careful of in a for loop. I'm merely reporting on things.

Still, I tried your sample code, and unfortunately it crashed.

I have a helper function that is calling this function for each folder recursively. I doubt that the helper function is what's causing this issue as I'm only passing folders and projects as fGiven.

Still stumped....

Very strange. I can confirm the crashes. It seems that calling 'getLinkModuleDescriptorsExclusive' in a 'for LinkModuleDescriptor in Folder' loop leaves DOORS in a random state, memorywise. If the routine is called repeatedly, the DXL errors slightly vary, and occur at different iterations of the foor loop, which is very confusing. Once, it even went into an infinite loop, and before all went gray, I could get a glimpse at my print statements, and it seemed as if 'strSourceName' was set to null this time. I would simply consider this a bug and use a workaround as scribbled together below, which first loops over all formal modules in the folder, retrieves the getLinkModuleDescriptorsExclusive value, stores it in a Skip list, and later retrieves the value from the Skip list.

Cheers,

Peter

void reportOnLMDs(Folder fGiven) 
{
    LinkModuleDescriptor LMD
        string               strSourceName
        ModName_             mn
        bool                 bExclusive
        Skip                 SmodList = createString
        Item                 Iitem
  if ((null fGiven) || (isDeleted fGiven)){return} 
        
  for Iitem in fGiven do
  {
    if (type Iitem != "Formal"){continue}
    mn         = module fullName Iitem
    bExclusive = getLinkModuleDescriptorsExclusive(fGiven, mn)
    put(SmodList, fullName Iitem, bExclusive)
  }
  
        for LMD in fGiven do 
        {
                strSourceName = (getSourceName LMD) ""
                if (strSourceName == ""){continue}
                if (find(SmodList, strSourceName, bExclusive))
                {
                  print "\n"
                  print (getSourceName LMD) "\t"
                  print (getTargetName LMD) "\t"
                  print (getName LMD) "\t"
                  print (getDescription LMD) "\t"
                  print (getMandatory LMD) "\t"
                  print (getOverridable LMD) "\t"
                  print bExclusive ""
                }
                else {print "\nERROR: '" strSourceName "' not found in list"}
        }
        delete SmodList
}

Re: Reporting on LinkModuleDescriptors
Mathias Mamsch - Mon Sep 10 04:28:56 EDT 2012

kbmurphy - Fri Sep 07 18:11:49 EDT 2012
Hey Louie,

Your explanation makes sense and doesn't at the same time. I'm not deleting anything, nor am I changing anything, and it's those two functions that you have to be careful of in a for loop. I'm merely reporting on things.

Still, I tried your sample code, and unfortunately it crashed.

I have a helper function that is calling this function for each folder recursively. I doubt that the helper function is what's causing this issue as I'm only passing folders and projects as fGiven.

Still stumped....

Well for me Louies explanation would make sense, if the getLinkModuleDescriptorsExclusive reloads an internal structure from the module, that the for LMD ... loop is relying on. But Louie already pulled out the getLinkModuleDescriptorsExclusive function from the loop and as you said the crash still happens. So that leaves as a possibility that the LinkModuleDescriptors that are stored in the skip list will be invalidated by calling getLinkModuleDescriptorsExclusive. Therefore you could try to a) load the link module descriptors exclusive flags before iterating over the LinkModuleDescriptors, or cache the link module descriptors before calling the getLinkModuleDescriptorsExclusive function.

I guess it would be adequate to file a bug report to IBM.

try this:

void reportOnLMDs(Folder fGiven) {    
        if ( (null fGiven) || (isDeleted fGiven) ) return
 
        LinkModuleDescriptor LMD
 
        Skip skExclusive = createString() 
        Item I
        for I in all in fGiven do {
           if (type I != "Formal" || isDeleted I) continue
           put (skExclusive , fullName I, (getLinkModuleDescriptorsExclusive(fGiven, module fullName I))
        } 
 
        for LMD in fGiven do {
                string strSourceName = (getSourceName LMD) ""
                bool bExclusive = false
                if (!find(skExclusive, strSourceName, bExclusive)) { 
                        /* some error handling would be appropriate? */
                        continue
                }
                print (getSourceName LMD) "\t"
                print (getTargetName LMD) "\t"
                print (getName LMD) "\t"
                print (getDescription LMD) "\t"
                print (getMandatory LMD) "\t"
                print (getOverridable LMD) "\t"
                print (bExclusive) "\n"
 
                // by the way, the 'exists' perm freaks me out somehow. I always assumed that a ModName_ 
                // is guaranteed to be NULL when the module does not exist... :-) 
                // if ((!isDeleted mn) && (exists mn)) ...
        }
        
}

 


Maybe that helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Re: Reporting on LinkModuleDescriptors
kbmurphy - Mon Sep 10 12:20:11 EDT 2012

Mathias Mamsch - Mon Sep 10 04:28:56 EDT 2012

Well for me Louies explanation would make sense, if the getLinkModuleDescriptorsExclusive reloads an internal structure from the module, that the for LMD ... loop is relying on. But Louie already pulled out the getLinkModuleDescriptorsExclusive function from the loop and as you said the crash still happens. So that leaves as a possibility that the LinkModuleDescriptors that are stored in the skip list will be invalidated by calling getLinkModuleDescriptorsExclusive. Therefore you could try to a) load the link module descriptors exclusive flags before iterating over the LinkModuleDescriptors, or cache the link module descriptors before calling the getLinkModuleDescriptorsExclusive function.

I guess it would be adequate to file a bug report to IBM.

try this:

void reportOnLMDs(Folder fGiven) {    
        if ( (null fGiven) || (isDeleted fGiven) ) return
 
        LinkModuleDescriptor LMD
 
        Skip skExclusive = createString() 
        Item I
        for I in all in fGiven do {
           if (type I != "Formal" || isDeleted I) continue
           put (skExclusive , fullName I, (getLinkModuleDescriptorsExclusive(fGiven, module fullName I))
        } 
 
        for LMD in fGiven do {
                string strSourceName = (getSourceName LMD) ""
                bool bExclusive = false
                if (!find(skExclusive, strSourceName, bExclusive)) { 
                        /* some error handling would be appropriate? */
                        continue
                }
                print (getSourceName LMD) "\t"
                print (getTargetName LMD) "\t"
                print (getName LMD) "\t"
                print (getDescription LMD) "\t"
                print (getMandatory LMD) "\t"
                print (getOverridable LMD) "\t"
                print (bExclusive) "\n"
 
                // by the way, the 'exists' perm freaks me out somehow. I always assumed that a ModName_ 
                // is guaranteed to be NULL when the module does not exist... :-) 
                // if ((!isDeleted mn) && (exists mn)) ...
        }
        
}

 


Maybe that helps, regards, Mathias

 

 


Mathias Mamsch, IT-QBase GmbH, Consultant for Requirement Engineering and D00RS

 

Thanks to everyone for weighing in. I'm going to file a bug report with IBM on this one. Both Peter and Mathias' code worked (although copy and pasters be warned, Mathias' code has two tiny syntax errors.)

Now that I'm a few days away from asking my original question, I see that every other function requires an LMD, but the getLinkModuleDescriptors function does not require an LMD. Whatever the reason for that is, is also likely the reason these crashes occur. I'm sure what IBM will do is not "fix" this bug, but rather update their documentation. We'll see.

Re: Reporting on LinkModuleDescriptors
llandale - Mon Sep 10 15:35:30 EDT 2012

kbmurphy - Fri Sep 07 18:11:49 EDT 2012
Hey Louie,

Your explanation makes sense and doesn't at the same time. I'm not deleting anything, nor am I changing anything, and it's those two functions that you have to be careful of in a for loop. I'm merely reporting on things.

Still, I tried your sample code, and unfortunately it crashed.

I have a helper function that is calling this function for each folder recursively. I doubt that the helper function is what's causing this issue as I'm only passing folders and projects as fGiven.

Still stumped....

It appears I was wrong in this case, but I was trying to suggest that the code was effectivly making this CompSci 101 mistake:
  • for i in some range do
  • {
    • for i in some other range do
    • {
      • whatever
    • }
    • deal with now corrupted "i"
  • }
That's different from my pet-peave advise to avoid this:
  • for each link in object do {delete(link)}